package com.ssy.lingxi.marketing.serviceimpl.feign;

import cn.hutool.json.JSONUtil;
import com.ssy.lingxi.common.constant.marketing.BelongTypeEnum;
import com.ssy.lingxi.common.constant.marketing.MerchantCouponTypeEnum;
import com.ssy.lingxi.common.constant.marketing.PlatformCouponTypeEnum;
import com.ssy.lingxi.common.response.Wrapper;
import com.ssy.lingxi.marketing.api.model.request.*;
import com.ssy.lingxi.marketing.api.model.response.CartOrderResp;
import com.ssy.lingxi.marketing.api.model.response.CouponInfoResp;
import com.ssy.lingxi.marketing.entity.coupon.CouponGoodsDO;
import com.ssy.lingxi.marketing.entity.coupon.MerchantCouponDetailDO;
import com.ssy.lingxi.marketing.entity.coupon.PlatformCouponDetailDO;
import com.ssy.lingxi.marketing.model.constant.CommonBooleanEnum;
import com.ssy.lingxi.marketing.model.constant.MerchantCouponDetailStatusEnum;
import com.ssy.lingxi.marketing.model.constant.PlatformCouponDetailStatusEnum;
import com.ssy.lingxi.marketing.repository.CouponGoodsRepository;
import com.ssy.lingxi.marketing.repository.CouponShopRepository;
import com.ssy.lingxi.marketing.repository.MerchantCouponDetailRepository;
import com.ssy.lingxi.marketing.repository.PlatformCouponDetailRepository;
import com.ssy.lingxi.marketing.service.feign.ICouponFeignService;
import com.ssy.lingxi.marketing.serviceimpl.component.coupon.CouponCacheComponent;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 优惠券内部接口服务实现类
 * @author yzc
 * @version 2.0.0
 * @date 2021/11/3
 */
@Slf4j
@Service
public class CouponFeignServiceImpl implements ICouponFeignService {

    @Resource
    private PlatformCouponDetailRepository platformCouponDetailRepository;
    @Resource
    private MerchantCouponDetailRepository merchantCouponDetailRepository;
    @Resource
    private CouponGoodsRepository couponGoodsRepository;
    @Resource
    private CouponShopRepository couponShopRepository;
    @Resource
    private CouponCacheComponent couponCacheComponent;

    @Override
    public Wrapper<List<CartOrderResp>> checkCouponAvailable(CartOrderReq req) {
        long currentTimeMillis = System.currentTimeMillis();
        List<Long> platformCouponDetailIdList = new ArrayList<>();
        List<Long> merchantCouponDetailIdList = new ArrayList<>();
        for (CouponAvailableReq couponAvailableReq : req.getCouponAvailableReqList()) {
            if (BelongTypeEnum.PLATFORM.getCode().equals(couponAvailableReq.getBelongType())) {
                platformCouponDetailIdList.add(couponAvailableReq.getCouponDetailId());
            } else if (BelongTypeEnum.MERCHANT.getCode().equals(couponAvailableReq.getBelongType())) {
                merchantCouponDetailIdList.add(couponAvailableReq.getCouponDetailId());
            }
        }

        // 平台优惠券
        List<PlatformCouponDetailDO> platformCouponDetailDOList = platformCouponDetailRepository.findAllById(platformCouponDetailIdList);
        // couponIdList
        List<Long> platformGoodsCouponIdList = platformCouponDetailDOList.stream().filter(e -> PlatformCouponTypeEnum.ZERO_DISCOUNT.getCode().equals(e.getCoupon().getType())).map(detail -> detail.getCoupon().getId()).collect(Collectors.toList());
        List<CouponGoodsDO> platformCouponGoodsDOList = couponGoodsRepository.findAllByBelongTypeAndCouponIdIn(BelongTypeEnum.PLATFORM.getCode(), platformGoodsCouponIdList);
        // couponId - goodsList
        Map<Long, List<CouponGoodsDO>> platformCouponGoodsMap = platformCouponGoodsDOList.stream().collect(Collectors.groupingBy(CouponGoodsDO::getCouponId));
        List<CartOrderResp> platformResultList = platformCouponDetailDOList.stream().map(e -> {
            CartOrderResp cartOrderResp = new CartOrderResp();
            Integer canUse = null;
            if (this.platformCheckCanUse(e, req.getMemberId(), req.getRoleId(), req.getShopId(), req.getOrderAmount(), currentTimeMillis)) {
                canUse = CommonBooleanEnum.YES.getCode();
            } else {
                canUse = CommonBooleanEnum.NO.getCode();
            }

            cartOrderResp.setCanUse(canUse);
            cartOrderResp.setCouponId(e.getCoupon().getId());
            cartOrderResp.setCouponDetailId(e.getId());
            cartOrderResp.setName(e.getCoupon().getName());
            cartOrderResp.setCouponType(e.getCoupon().getType());
            cartOrderResp.setBelongType(BelongTypeEnum.PLATFORM.getCode());
            cartOrderResp.setDenomination(e.getCoupon().getDenomination());
            cartOrderResp.setValidTimeStart(e.getValidTimeStart());
            cartOrderResp.setValidTimeEnd(e.getValidTimeEnd());
            List<Long> suitableSkuIdList = Optional.ofNullable(platformCouponGoodsMap.get(e.getCoupon().getId())).map(list -> list.stream().map(CouponGoodsDO::getSkuId).collect(Collectors.toList())).orElse(Collections.emptyList());
            cartOrderResp.setSuitableSkuIdList(suitableSkuIdList);
            return cartOrderResp;
        }).collect(Collectors.toList());

        // 商家优惠券
        List<MerchantCouponDetailDO> merchantCouponDetailDOList = merchantCouponDetailRepository.findAllById(merchantCouponDetailIdList);
        // couponIdList
        List<Long> merchantGoodsCouponIdList = merchantCouponDetailDOList.stream().filter(e -> Arrays.asList(MerchantCouponTypeEnum.ZERO_DISCOUNT.getCode(), MerchantCouponTypeEnum.COMMODITY.getCode()).contains(e.getCoupon().getType())).map(detail -> detail.getCoupon().getId()).collect(Collectors.toList());
        List<CouponGoodsDO> merchantCouponGoodsDOList = couponGoodsRepository.findAllByBelongTypeAndCouponIdIn(BelongTypeEnum.MERCHANT.getCode(), merchantGoodsCouponIdList);
        // couponId - goodsList
        Map<Long, List<CouponGoodsDO>> merchantCouponGoodsMap = merchantCouponGoodsDOList.stream().collect(Collectors.groupingBy(CouponGoodsDO::getCouponId));
        List<CartOrderResp> merchantResultList = merchantCouponDetailDOList.stream().map(e -> {
            CartOrderResp cartOrderResp = new CartOrderResp();
            cartOrderResp.setVendorMemberId(e.getMemberId());
            cartOrderResp.setVendorRoleId(e.getRoleId());
            Integer canUse = null;
            if (this.merchantCheckCanUse(e, req.getMemberId(), req.getRoleId(), req.getShopId(), req.getOrderAmount(), currentTimeMillis)) {
                canUse = CommonBooleanEnum.YES.getCode();
            } else {
                canUse = CommonBooleanEnum.NO.getCode();
            }

            cartOrderResp.setCanUse(canUse);
            cartOrderResp.setCouponId(e.getCoupon().getId());
            cartOrderResp.setCouponDetailId(e.getId());
            cartOrderResp.setName(e.getCoupon().getName());
            cartOrderResp.setCouponType(e.getCoupon().getType());
            cartOrderResp.setBelongType(BelongTypeEnum.MERCHANT.getCode());
            cartOrderResp.setDenomination(e.getCoupon().getDenomination());
            cartOrderResp.setValidTimeStart(e.getValidTimeStart());
            cartOrderResp.setValidTimeEnd(e.getValidTimeEnd());
            List<Long> suitableSkuIdList = Optional.ofNullable(merchantCouponGoodsMap.get(e.getCoupon().getId())).map(list -> list.stream().map(CouponGoodsDO::getSkuId).collect(Collectors.toList())).orElse(Collections.emptyList());
            cartOrderResp.setSuitableSkuIdList(suitableSkuIdList);
            return cartOrderResp;
        }).collect(Collectors.toList());

        // 平台优惠券,商家优惠券相加
        platformResultList.addAll(merchantResultList);

        return Wrapper.success(platformResultList);
    }

    @Override
    public Wrapper<Void> consumeCoupon(CouponConsumeReq req) {
        log.info("内部接口订单消耗优惠券, req:{}", JSONUtil.toJsonStr(req));
        List<CouponDetailConsumeReq> couponDetailList = req.getCouponDetailList();
        if (CollectionUtils.isEmpty(couponDetailList)) {
            return Wrapper.success();
        }
        Map<Integer, List<CouponDetailConsumeReq>> couponDetailMap = couponDetailList.stream().collect(Collectors.groupingBy(CouponDetailConsumeReq::getBelongType));

        List<CouponDetailConsumeReq> platformCouponDetailReqList = couponDetailMap.get(BelongTypeEnum.PLATFORM.getCode());
        if (!CollectionUtils.isEmpty(platformCouponDetailReqList)) {
            List<Long> platformDetailCouponIds = platformCouponDetailReqList.stream().map(CouponDetailConsumeReq::getCouponDetailId).collect(Collectors.toList());
            List<PlatformCouponDetailDO> platformCouponDetailDOList = platformCouponDetailRepository.findAllById(platformDetailCouponIds);

            platformCouponDetailDOList.forEach(e -> {
                e.setStatus(PlatformCouponDetailStatusEnum.USE.getCode());
                e.setOrderNo(req.getOrderNo());
                e.setAmount(req.getTotalAmount());
                e.setShopId(req.getShopId());
                e.setShopName(req.getShopName());
                e.setUseTime(req.getOrderCreateTime());
            });

            platformCouponDetailRepository.saveAll(platformCouponDetailDOList);
        }
        List<CouponDetailConsumeReq> merchantCouponDetailReqList = couponDetailMap.get(BelongTypeEnum.MERCHANT.getCode());
        if (!CollectionUtils.isEmpty(merchantCouponDetailReqList)) {
            List<Long> merchantDetailCouponIds = merchantCouponDetailReqList.stream().map(CouponDetailConsumeReq::getCouponDetailId).collect(Collectors.toList());
            List<MerchantCouponDetailDO> merchantCouponDetailDOList = merchantCouponDetailRepository.findAllById(merchantDetailCouponIds);

            merchantCouponDetailDOList.forEach(e -> {
                e.setStatus(MerchantCouponDetailStatusEnum.USE.getCode());
                e.setOrderNo(req.getOrderNo());
                e.setAmount(req.getTotalAmount());
                e.setShopId(req.getShopId());
                e.setShopName(req.getShopName());
                e.setUseTime(req.getOrderCreateTime());
            });

            merchantCouponDetailRepository.saveAll(merchantCouponDetailDOList);
        }

        return Wrapper.success();
    }

    @Override
    public Wrapper<Void> returnCoupon(List<CouponDetailConsumeReq> req) {
        log.info("内部接口取消订单返还优惠券, req:{}", JSONUtil.toJsonStr(req));
        long currentTimeMillis = System.currentTimeMillis();

        Map<Integer, List<CouponDetailConsumeReq>> couponDetailMap = req.stream().collect(Collectors.groupingBy(CouponDetailConsumeReq::getBelongType));

        List<CouponDetailConsumeReq> platformCouponDetailReqList = couponDetailMap.get(BelongTypeEnum.PLATFORM.getCode());
        if (!CollectionUtils.isEmpty(platformCouponDetailReqList)) {
            List<Long> platformDetailCouponIds = platformCouponDetailReqList.stream().map(CouponDetailConsumeReq::getCouponDetailId).collect(Collectors.toList());
            List<PlatformCouponDetailDO> platformCouponDetailDOList = platformCouponDetailRepository.findAllById(platformDetailCouponIds);

            platformCouponDetailDOList.forEach(e -> {
                if (e.getValidTimeEnd() < currentTimeMillis) {
                    e.setStatus(PlatformCouponDetailStatusEnum.EXPIRE.getCode());
                } else {
                    e.setStatus(PlatformCouponDetailStatusEnum.RECEIVE.getCode());
                }
                e.setOrderNo(null);
                e.setShopId(null);
                e.setShopName(null);
                e.setUseTime(null);
                e.setAmount(null);
            });

            platformCouponDetailRepository.saveAll(platformCouponDetailDOList);
        }
        List<CouponDetailConsumeReq> merchantCouponDetailReqList = couponDetailMap.get(BelongTypeEnum.MERCHANT.getCode());
        if (!CollectionUtils.isEmpty(merchantCouponDetailReqList)) {
            List<Long> merchantDetailCouponIds = merchantCouponDetailReqList.stream().map(CouponDetailConsumeReq::getCouponDetailId).collect(Collectors.toList());
            List<MerchantCouponDetailDO> merchantCouponDetailDOList = merchantCouponDetailRepository.findAllById(merchantDetailCouponIds);

            merchantCouponDetailDOList.forEach(e -> {
                if (e.getValidTimeEnd() < currentTimeMillis) {
                    e.setStatus(PlatformCouponDetailStatusEnum.EXPIRE.getCode());
                } else {
                    e.setStatus(PlatformCouponDetailStatusEnum.RECEIVE.getCode());
                }
                e.setOrderNo(null);
                e.setShopId(null);
                e.setShopName(null);
                e.setUseTime(null);
                e.setAmount(null);
            });

            merchantCouponDetailRepository.saveAll(merchantCouponDetailDOList);
        }

        return Wrapper.success();
    }

    private boolean platformCheckCanUse(PlatformCouponDetailDO detailDO, Long memberId, Long roleId, Long shopId, BigDecimal orderAmount, Long currentTimeMillis) {
        if (!detailDO.getSubMemberId().equals(memberId)
                || !detailDO.getSubRoleId().equals(roleId)) {
            log.error("平台优惠券不属于当前用户: couponDetailId: {}, memberId: {}, roleId: {}", detailDO.getId(), memberId, roleId);
            return false;
        }

        if (!PlatformCouponDetailStatusEnum.RECEIVE.getCode().equals(detailDO.getStatus())) {
            log.error("平台优惠券非未使用状态: couponDetailId: {}, status: {}", detailDO.getId(), detailDO.getStatus());
            return false;
        }

        boolean suitableShopFlag = couponShopRepository.existsByBelongTypeAndCouponIdAndShopId(BelongTypeEnum.PLATFORM.getCode(), detailDO.getCoupon().getId(), shopId);
        if (!suitableShopFlag) {
            log.error("平台优惠券不能使用在该商城: couponDetailId: {}", detailDO.getId());
            return false;
        }

        if (detailDO.getCoupon().getUseConditionMoney().compareTo(orderAmount) > 0) {
            log.error("平台优惠券不满足订单金额: couponDetailId: {}, useConditionMoney: {}, orderAmount: {}", detailDO.getId(), detailDO.getCoupon().getUseConditionMoney(), orderAmount);
            return false;
        }

        if (currentTimeMillis < detailDO.getValidTimeStart()
                || currentTimeMillis > detailDO.getValidTimeEnd()) {
            log.error("平台优惠券不满足有效期: couponDetailId: {}, currentTime: {}, validateTimeStart: {}, validateTimeEnd: {}", detailDO.getId(), currentTimeMillis, detailDO.getValidTimeStart(), detailDO.getValidTimeEnd());
            return false;
        }

        return true;
    }

    private boolean merchantCheckCanUse(MerchantCouponDetailDO detailDO, Long memberId, Long roleId, Long shopId, BigDecimal orderAmount, Long currentTimeMillis) {
        if (!detailDO.getSubMemberId().equals(memberId)
                || !detailDO.getSubRoleId().equals(roleId)) {
            log.error("商家优惠券不属于当前用户: couponDetailId: {}, memberId: {}, roleId: {}", detailDO.getId(), memberId, roleId);
            return false;
        }

        if (!MerchantCouponDetailStatusEnum.RECEIVE.getCode().equals(detailDO.getStatus())) {
            log.error("商家优惠券非未使用状态: couponDetailId: {}, status: {}", detailDO.getId(), detailDO.getStatus());
            return false;
        }

        boolean suitableShopFlag = couponShopRepository.existsByBelongTypeAndCouponIdAndShopId(BelongTypeEnum.MERCHANT.getCode(), detailDO.getCoupon().getId(), shopId);
        if (!suitableShopFlag) {
            log.error("商家优惠券不能使用在该商城: couponDetailId: {}", detailDO.getId());
            return false;
        }

        if (detailDO.getCoupon().getUseConditionMoney().compareTo(orderAmount) > 0) {
            log.error("商家优惠券不满足订单金额: couponDetailId: {}, useConditionMoney: {}, orderAmount: {}", detailDO.getId(), detailDO.getCoupon().getUseConditionMoney(), orderAmount);
            return false;
        }

        if (currentTimeMillis < detailDO.getValidTimeStart()
                || currentTimeMillis > detailDO.getValidTimeEnd()) {
            log.error("商家优惠券不满足有效期: couponDetailId: {}, currentTime: {}, validateTimeStart: {}, validateTimeEnd: {}", detailDO.getId(), currentTimeMillis, detailDO.getValidTimeStart(), detailDO.getValidTimeEnd());
            return false;
        }

        return true;
    }

    @Override
    public Wrapper<List<CouponInfoResp>> getCouponDetailListByIds(CouponQueryReq req) {
        Integer belongType=BelongTypeEnum.PLATFORM.getCode();
        if(req.getBelongType()!=null){
            belongType=req.getBelongType();
        }
        List<CouponInfoResp> respList=null;
        if(BelongTypeEnum.PLATFORM.getCode().equals(belongType)){
            List<PlatformCouponDetailDO> pfCouponList = platformCouponDetailRepository.findAllById(req.getCouponIds());
            if(!CollectionUtils.isEmpty(pfCouponList)){
                respList=pfCouponList.stream().map(o -> new CouponInfoResp(o.getId(),o.getCode())).collect(Collectors.toList());
            }
        }else if(BelongTypeEnum.MERCHANT.getCode().equals(belongType)){
            List<MerchantCouponDetailDO> merchantCouponList = merchantCouponDetailRepository.findAllById(req.getCouponIds());
            if(!CollectionUtils.isEmpty(merchantCouponList)){
                respList=merchantCouponList.stream().map(o -> new CouponInfoResp(o.getId(),o.getCode())).collect(Collectors.toList());
            }
        }
        return Wrapper.success(respList);
    }
}
